Texture2D rect_texture;

SamplerState point_sampler
{
    Filter = MIN_MAG_MIP_POINT;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct GSRectIn
{
    float4 source : SOURCE;
    float4 dest : DESTINATION;
    float4 color : COLOR;
    float depth : DEPTH;
    float rotation : ROTATION;
};

struct PSRectIn
{
    float4 pos : SV_Position;
    float4 color : COLOR0;
    float2 tex : TEXTURE0;
};

BlendState AlphaBlending
{
    BlendEnable[0] = TRUE;
    SrcBlend = SRC_ALPHA;
    DestBlend = INV_SRC_ALPHA;
    BlendOp = ADD;
    SrcBlendAlpha = ONE;
    DestBlendAlpha = ONE;
    BlendOpAlpha = ADD;
};

DepthStencilState DisableDepth
{
    DepthEnable = FALSE;
    DepthWriteMask = ZERO;
};

GSRectIn VSpass(GSRectIn input)
{
    return input;
}

[maxvertexcount(4)]
void GSRects(point GSRectIn inp[1], inout TriangleStream<PSRectIn> stream_output)
{
    PSRectIn output;
    
    GSRectIn input = inp[0];
    
    float2 one = float2(1.0f, 1.0f);
    float2 flip_y = float2(1.0f, -1.0f);

    float2 top_left = (input.dest.xy * 2 - one) * flip_y;
    float2 bottom_left = (input.dest.xw * 2 - one) * flip_y;
    float2 top_right = (input.dest.zy * 2 - one) * flip_y;
    float2 bottom_right = (input.dest.zw * 2 - one) * flip_y;

    float2 tex_top_left = input.source.xy;
    float2 tex_bottom_left = input.source.xw;
    float2 tex_top_right = input.source.zy;
    float2 tex_bottom_right = input.source.zw;
    
    output.pos = float4(top_left, input.depth, 1.0f);
    output.color = input.color;
    output.tex = tex_top_left;
    stream_output.Append(output);

    output.pos = float4(top_right, input.depth, 1.0f);
    output.color = input.color;
    output.tex = tex_top_right;
    stream_output.Append(output);

    output.pos = float4(bottom_left, input.depth, 1.0f);
    output.color = input.color;
    output.tex = tex_bottom_left;
    stream_output.Append(output);
    
    output.pos = float4(bottom_right, input.depth, 1.0f);
    output.color = input.color;
    output.tex = tex_bottom_right;
    stream_output.Append(output);

    stream_output.RestartStrip();
}

float4 PSRects(PSRectIn input) : SV_Target
{
    return rect_texture.Sample(point_sampler, input.tex) * input.color;
}

technique10 t1
{
    pass p0
    {
        SetVertexShader( CompileShader( vs_4_0, VSpass() ));
        SetGeometryShader( CompileShader( gs_4_0, GSRects() ));
        SetPixelShader( CompileShader( ps_4_0, PSRects() ));
        SetBlendState( AlphaBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
        SetDepthStencilState( DisableDepth, 0 );
    }
}

